package com.hn.zhijian.system.rsasdk;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;

/**
 * AES加解密算法
 * 
 * @author shaohai.Liu
 * @date 2017-8-7
 * @version 0.0.1-SNAPSHOT
 */
public class AES extends AbstractSecurity {
	/**
	 * KEY长度
	 */
	final int base = 16;

	/**
	 * 算法名称
	 */
	final String KEY_ALGORITHM = "AES";

	/**
	 * 加解密算法/模式/填充方式
	 */
	final String algorithmStr = "AES/CBC/PKCS5Padding";

	/**
	 * KEY
	 */
	private Key key;

	/**
	 * 
	 */
	private Cipher cipher;

	/**
	 * 是否初始化
	 */
	boolean isInited = false;

	/**
	 * 向量
	 */
	private byte[] iv;

	/**
	 * 设置向量
	 * 
	 * @param iv
	 *            向量
	 */
	public void setIv(byte[] iv) {
		this.iv = iv;
	}

	/**
	 * 初始化
	 * 
	 * @param keyBytes
	 *            密钥
	 * @throws SecurityException
	 *             加解密错误
	 */
	public void init(byte[] keyBytes) throws SecurityException {
		// 实例化密钥生成器
		try {
			if (keyBytes.length % base != 0) {
				int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
				byte[] temp = new byte[groups * base];
				Arrays.fill(temp, (byte) 0);
				System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
				keyBytes = temp;
			}

			// 初始化
			Security.addProvider(new BouncyCastleProvider());
			// 转化成JAVA的密钥格式
			key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);

			// 初始化cipher
			cipher = Cipher.getInstance(algorithmStr, "BC");
		} catch (NoSuchAlgorithmException e) {
			throw new SecurityException(e);
		} catch (NoSuchPaddingException e) {
			throw new SecurityException(e);
		} catch (NoSuchProviderException e) {
			throw new SecurityException(e);
		}
	}

	/**
	 * 加密方法
	 * 
	 * @param content
	 *            要加密的字符串
	 * @param keyBytes
	 *            加密密钥
	 * @return 加密后的字节码
	 * @throws SecurityException
	 *             加解密错误
	 */
	public byte[] encrypt(byte[] content, byte[] keyBytes) throws SecurityException {
		byte[] encryptedText = null;
		init(keyBytes);

		try {
			cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
			encryptedText = cipher.doFinal(content);
		} catch (Exception e) {
			throw new SecurityException(e);
		}

		return encryptedText;
	}

	/**
	 * 解密方法
	 * 
	 * @param encryptedData
	 *            要解密的字符串
	 * @param keyBytes
	 *            解密密钥
	 * @return 解密后的字节码
	 * @throws SecurityException
	 *             加解密错误
	 */
	public byte[] decrypt(byte[] encryptedData, byte[] keyBytes) throws SecurityException {
		byte[] encryptedText = null;
		init(keyBytes);

		try {
			cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));

			encryptedText = cipher.doFinal(encryptedData);
		} catch (Exception e) {
			throw new SecurityException(e);
		}

		return encryptedText;
	}
}
